package org.flexthinker.binding.bean
{
    import org.flexthinker.binding.value.support.MockBean;
    import org.hamcrest.assertThat;
    import org.hamcrest.core.throws;
    import org.hamcrest.object.equalTo;
    import org.hamcrest.object.instanceOf;
    import org.hamcrest.object.notNullValue;

    public class BindingGroupTest
    {
        private var group:BindingGroup;
        private var sourceBean:MockBean;
        private var targetBean:MockBean;

        private var b:Binding;
        private var b2:Binding;

        public function BindingGroupTest()
        {
        }

        [Before]
        public function setUp():void
        {
            group = new BindingGroup();
            sourceBean = new MockBean();
            targetBean = new MockBean();

            b = new AutoBinding(UpdateStrategy.READ_WRITE, sourceBean, BeanProperty.create("simpleString"),
                    targetBean, BeanProperty.create("simpleString"));
            b2 = new AutoBinding(UpdateStrategy.READ_WRITE, sourceBean, BeanProperty.create("simpleNumber"),
                    targetBean, BeanProperty.create("simpleNumber"));
        }

        [Test]
        public function testInitialization():void
        {
            assertThat(group.getBindingListeners(), notNullValue());
            assertThat( group.getBindings().length, equalTo(0) );
        }

        [Test]
        public function testAddRemoveListeners():void
        {
            var l:BindingListener = new BindingListenerCounter();
            group.addBindingListener(l);
            assertThat(group.getBindingListeners().length, equalTo(1));
            group.addBindingListener(l);
            assertThat(group.getBindingListeners().length, equalTo(1));
            group.removeBindingListener(l);
            assertThat(group.getBindingListeners().length, equalTo(0));
            group.removeBindingListener(l);
            assertThat(group.getBindingListeners().length, equalTo(0));
        }

        [Test]
        public function testAddBinding():void
        {
            b.bind();

            group.addBinding(b);
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(0));
            assertThat(group.getBindings().length, equalTo(1));

            group.addBinding(b2);
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(1));
            assertThat(group.getBindings().length, equalTo(2));

            group.bind();
            assertThat(group.bound.length, equalTo(2));
            assertThat(group.unbound.length, equalTo(0));

            b.unbind();
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(1));

            b2.unbind();
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(2));

            assertThat("shouldn't be able to add same Binding twice",
                    function():void
                    {
                        group.addBinding(b2);
                    },
                    throws(instanceOf(ArgumentError)));
        }

        [Test]
        public function testRemoveBinding():void
        {
            group.addBinding(b);
            group.addBinding(b2);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(2));

            group.removeBinding(b);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(1));

            b.bind();
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(1));

            b2.bind();
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(0));

            group.removeBinding(b2);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(0));

            group.removeBinding(b2);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(0));
        }

        [Test]
        public function testBind():void
        {
            group.addBinding(b);

            group.bind();
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(0));

            group.addBinding(b2);
            assertThat(group.bound.length, equalTo(1));
            assertThat("BindingGroup shouldn't automatically bind the newly added Bindings",group.unbound.length, equalTo(1));

            group.bind();
            assertThat(group.bound.length, equalTo(2));
            assertThat(group.unbound.length, equalTo(0));
        }

        [Test]
        public function testUnbind():void
        {
            group.addBinding(b);
            group.addBinding(b2);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(2));

            group.unbind();
            group.unbind();

            b.bind();
            assertThat(group.bound.length, equalTo(1));
            assertThat(group.unbound.length, equalTo(1));

            group.bind();
            assertThat(group.bound.length, equalTo(2));
            assertThat(group.unbound.length, equalTo(0));

            group.unbind();
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(2));

            group.removeBinding(b2);
            assertThat(group.bound.length, equalTo(0));
            assertThat(group.unbound.length, equalTo(1));
        }


    }
}
